package com.miaoshare.core.utils.oss;

import android.content.Context;
import android.os.Handler;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSFederationToken;
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider;
import com.alibaba.sdk.android.oss.model.CompleteMultipartUploadResult;
import com.alibaba.sdk.android.oss.model.MultipartUploadRequest;
import com.alibaba.sdk.android.oss.model.OSSRequest;
import com.miaoshare.core.BuildConfig;
import com.miaoshare.core.utils.DateUtil;

import java.util.HashMap;
import java.util.Map;

import okhttp3.Response;

/**
 * Created by zxs
 * on 2022/2/15
 */
public class UploadFileUtil {

    public String bucketName = "*****";
    /*上传文件目录*/
    private String mSetObjectName = "";

    public String getBucketName() {
        return bucketName;
    }

    private static UploadFileUtil instance;
    private Context context;
    OSS oss;
    Handler mHandler = new Handler();
    /*请求域名*/
    public static String httpName = "http:****";

    public static UploadFileUtil get() {
        if (instance == null) {
            instance = new UploadFileUtil();
        }
        return instance;
    }

    public void init(Context context) {
        this.context = context;
        bucketName = BuildConfig.DEBUG ? "****" : "*****";
        initial();
    }

    /*设置图片上传文件夹*/
    public void setObjectName(String setObjectName) {
        mSetObjectName = setObjectName;
    }

    private void initial() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (BuildConfig.DEBUG) {
                    OSSLog.enableLog();
                }
                // endpoint 与后台配置相同
                String endpoint = BuildConfig.DEBUG ? "oss-cn-beijing.aliyuncs.com" : " oss-cn-shenzhen.aliyuncs.com";
                //推荐使用OSSAuthCredentialsProvider。token过期可以及时更新
                OSSFederationToken token = getSecurityToken();
                if (token == null) {
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            initial();
                        }
                    }, 5_000);
                    return;
                }
                OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(token) {
                    @Override
                    public OSSFederationToken getFederationToken() {
                        return UploadFileUtil.this.getSecurityToken();
                    }
                };
                //该配置类如果不设置，会有默认配置，具体可看该类
                ClientConfiguration conf = new ClientConfiguration();
                conf.setConnectionTimeout(30 * 1000); // 连接超时，默认15秒
                conf.setSocketTimeout(30 * 1000); // socket超时，默认15秒
                conf.setMaxConcurrentRequest(5); // 最大并发请求数，默认5个
                conf.setMaxErrorRetry(2); // 失败后最大重试次数，默认2次
                oss = new OSSClient(context, endpoint, credentialProvider);
            }
        }).start();
    }

    private OSSFederationToken getSecurityToken() {
        try {
            Map<String, String> params = new HashMap<>();
            //参数自行约定
            params.put("token_name", "token_name");
            Response response = new SimpleCall().callUrl(httpName + "具体接口地址", params);
            OSSInfo result = JSONObject.parseObject(response.body().string(), new TypeReference<OSSInfo>() {
            });
            if (result == null) {
                result = new OSSInfo();
            }
            return new OSSFederationToken(result.getAccessKeyId(), result.getAccessKeySecret(),
                    result.getSecurityToken(), result.getExpiration());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void uploadFileMultipart(String filePath, final UploadFileCallback callback) {
        String name = UUIDUtil.getUUID() + filePath.substring(filePath.lastIndexOf("."));
        MultipartUploadRequest<MultipartUploadRequest> request = new MultipartUploadRequest<>(getBucketName(), mSetObjectName + DateUtil.getNowDateTimePic() + "/" + name,
                filePath);
        request.setCRC64(OSSRequest.CRC64Config.YES);
        request.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() {

            @Override
            public void onProgress(final MultipartUploadRequest request, final long currentSize, final long totalSize) {
                OSSLog.logDebug("[testMultipartUpload] - " + currentSize + " " + totalSize, false);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onProgress(request, currentSize, totalSize);
                    }
                });
            }
        });
        oss.asyncMultipartUpload(request, new OSSCompletedCallback<MultipartUploadRequest, CompleteMultipartUploadResult>() {
            @Override
            public void onSuccess(final MultipartUploadRequest request, final CompleteMultipartUploadResult result) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onSuccess(request, result);
                    }
                });
            }

            @Override
            public void onFailure(final MultipartUploadRequest request, final ClientException clientException, final ServiceException serviceException) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (callback != null)
                            callback.onFailure(request, clientException, serviceException);
                    }
                });
            }
        });
    }

    public interface UploadFileCallback {
        void onProgress(MultipartUploadRequest request, long currentSize, long totalSize);

        void onSuccess(MultipartUploadRequest request, CompleteMultipartUploadResult result);

        void onFailure(MultipartUploadRequest request, ClientException clientException, ServiceException serviceException);
    }
}
